package com.comp6231.client;

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;

import org.omg.CORBA.ORB;

import java.sql.Date;
import java.util.Scanner;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import DPIS.StationServer;
import DPIS.StationServerHelper;

import com.comp6231.common.Log;
import com.comp6231.replica1.data.Stations;
import com.comp6231.replica1.exception.LogOperationException;

/**
 * 
 * This is the DPIS client system's main class
 * This class verify police offices badge numbers
 * and then connect to servers and provide options
 * to perform operations allowed by server 
 *
 * @author sknarula (narula.sk@gmail.com)
 * @since September 2013
 * 
 * 
 */
public class OfficerClient {

	/**
	 * Class attributes to hold the badge number of the office 
	 * using the system currently and the server refernce
	 */
	static String badgeId = null;
	static String stationName = null;
	static Scanner keyboard = new Scanner(System.in);
	
	/**
	 * Declare the server
	 */
	StationServer server = null;
	// save the reference to avoid unnecessary I/O
	String feIOR = null;

	/**
	 * Constructor to lookup the server object based on station name provided
	 * 
	 * @param stationName
	 * @throws RemoteException
	 * @throws NotBoundException
	 * @throws MalformedURLException
	 */
	public OfficerClient(String[] args, String stationName)   
			throws IOException {
		
		ORB orb = ORB.init(args, null);
		
		// check if the ior is saved (it is saved upon using it once)
		String ior = feIOR;
		if (ior == null) {
			// accessing the server first time, so get it from file
			BufferedReader br = new BufferedReader(new FileReader(System.getProperty("user.dir")
					+ "/src/com/comp6231/frontend/"
					+ "FEIor.txt"));
			ior = br.readLine();
			br.close();	
			feIOR = ior;
		}
		
		org.omg.CORBA.Object o = orb.string_to_object(ior);
		
		server = StationServerHelper.narrow(o);
	}
	
	/**
	 * Main method to start the client thread
	 * 
	 * @param args
	 */
	public static void main(String[] args) {
		int length = args.length;
		for (int i=0; i<length; i++) {
			System.out.println(args[i]);
		}
		
		System.out.println("\nOfficer Client System started...Welcome\n");
		// get the badge id from user and set the badge id and station name
		getAndVerifyBadgeId();
		
		try {
			OfficerClient client = new OfficerClient(args, stationName);
			client.run();
		} catch (IOException e) {
			System.out.println("Officer Client could not connect to the server.");
			e.printStackTrace();
		}
	}
	
	/**
	 * Start the thread, display menu and perform tasks based on user input
	 */
	public void run()
	{
		char userInput;
		do
		{
			displayMenu();
			String stringInput = keyboard.nextLine();
			userInput = stringInput.charAt(0);
			
			try
			{
				String firstName = "";
				String lastName = "";
				String status = "";
				String recordId = "";				
				boolean success = false;
				Log log = null;
				
				switch ( userInput ) {
					case '1':		// create criminal record
						String crimeDesc = "";
						
						System.out.println("Criminal first name: ");
						firstName = keyboard.nextLine();
						System.out.println("Criminal last name: ");
						lastName = keyboard.nextLine();
						System.out.println("Crime description: ");
						crimeDesc = keyboard.nextLine();
						System.out.println("Criminal Status (captured/otr): ");
						status = keyboard.nextLine().toUpperCase();
						
						success = server.createCRecord(badgeId, firstName, lastName, crimeDesc, status);

						// log the creation of the record
						log = new Log(System.getProperty("user.dir") + "/src/com/comp6231/client/logs/" + badgeId + ".txt",
								"Requested Creation of Criminal Record", badgeId, (success ? "Operation Successful" : "Operation Failed: See server log for details"));
						log.save();							
						
						System.out.println("\n");
						break;
				
					case '2':		// create missing record
						String address = "";
						String missingFrom = "";
						String missingSince = "";
						
						System.out.println("Missing person's first name: ");
						firstName = keyboard.nextLine();
						System.out.println("Missing person's last name: ");
						lastName = keyboard.nextLine();
						System.out.println("Missing person's address: ");
						address = keyboard.nextLine();
						System.out.println("Missing since (yyyy-mm-dd): ");
						missingSince = keyboard.nextLine();
						System.out.println("Missing from: ");
						missingFrom = keyboard.nextLine();						
						System.out.println("Missing Status (missing/found): ");
						status = keyboard.nextLine().toUpperCase();
						
						// this is just a check now, although I am sending date as a string to server 
						try {
							Date.valueOf(missingSince);
						} catch (IllegalArgumentException e) {
							System.out.println("\nInvalid Date is entered, can't create record at this moment");
							break;
						}
						
						success = server.createMRecord(badgeId, firstName, lastName, address, missingSince, missingFrom, status);

						// log the creation of the record
						log = new Log(System.getProperty("user.dir") + "/src/com/comp6231/client/logs/" + badgeId + ".txt",
								"Requested Creation of Missing Record", badgeId, (success ? "Operation Successful" : "Operation Failed: See server log for details"));
						log.save();	
						
						System.out.println("\n");
						break;
					
					case '3':		// edit a record
						String newStatus = "";
						
						System.out.println("Last name in record: ");
						lastName = keyboard.nextLine();
						System.out.println("Record id to modify: ");
						recordId = keyboard.nextLine();
						System.out.println("New Status: ");
						newStatus = keyboard.nextLine().toUpperCase();
						
						success = server.editRecord(badgeId, lastName, recordId, newStatus);

						// log the creation of the record
						log = new Log(System.getProperty("user.dir") + "/src/com/comp6231/client/logs/" + badgeId + ".txt",
								"Requested Editing of Record", badgeId, (success ? "Operation Successful" : "Operation Failed: See server log for details"));
						log.save();							
						
						System.out.println("\n");
						break;
						
					case '4':		// get record count
						String countReturned = server.getRecordCounts(badgeId);
						System.out.println(countReturned);

						// log the creation of the record
						log = new Log(System.getProperty("user.dir") + "/src/com/comp6231/client/logs/" + badgeId + ".txt",
								"Requested Record Count", badgeId, "Count Returned: \"" + countReturned + "\"");
						log.save();	
						
						System.out.println("\n");
						break;				
						
					case '5':		// transfer a record
							String newStationServerName = "";
							
							System.out.println("Record id to tranfer: ");
							recordId = keyboard.nextLine();
							System.out.println("Name of the remote server to tranfer to: ");
							newStationServerName = keyboard.nextLine();
							
							success = server.transferRecord(badgeId, recordId, newStationServerName.toUpperCase());

							// log the creation of the record
							log = new Log(System.getProperty("user.dir") + "/src/com/comp6231/client/logs/" + badgeId + ".txt",
									"Requested transfer of Record", badgeId, (success ? "Operation Successful" : "Operation Failed: See server log for details"));
							log.save();							
							
							System.out.println("\n");
							break;
						
				}
			}
			catch (LogOperationException e )
			{
				System.out.println(e.getMessage());
				System.out.println("\n");
			}
		} while ( userInput != 'q' && userInput != 'Q' );
	}
	
	/**
	 * Method to display the menu 
	 */
	private void displayMenu()
	{
		System.out.println("\nOptions: ");
		System.out.println("1:	Create Criminal Record");
		System.out.println("2:	Create Missing Record");
		System.out.println("3:	Edit a Record");		
		System.out.println("4:	Get Record Count");
		System.out.println("5:	Transfer Record");
		System.out.println("6:	Print Hashtable to File");
		System.out.println("q:	Quit");
		
		System.out.println("\nPlease enter your choice.");
	}
	
	/**
	 * method to get police officer badge number and 
	 * verify it to ensure its a valid 
	 */
	private static void getAndVerifyBadgeId() {
		// input the badge id
		String userInput = null;
		System.out.println("\nPlease enter you Badge Id to log on: ");
		userInput = keyboard.nextLine();
		
		// verify and save the badge id
		Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher(userInput); 
        String tempStationName = "";
		try {			
			matcher.find();
			tempStationName = userInput.substring(0, userInput.indexOf(matcher.group())).toUpperCase();
			stationName = Stations.getEnumValue(tempStationName).getPoliceStationType();
			
			badgeId = userInput;
			System.out.println("Welcome officer " + badgeId + ", you will be now connected to station " + stationName);
			
		}
		catch (IllegalArgumentException e) {
			System.out.println(tempStationName + " Not a valid station");
			getAndVerifyBadgeId();
		}
		catch (IllegalStateException e) {
			System.out.println(tempStationName + " Not a valid station");
			getAndVerifyBadgeId();
		}
		catch (NullPointerException e) {
			System.out.println("Station cannot be null");
			getAndVerifyBadgeId();
		}
		
	}
}
